package com.sqx.modules.health.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sqx.common.utils.RedisUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.utils.JwtUtils;
import com.sqx.modules.health.common.Constants;
import com.sqx.modules.health.common.RoleEnum;
import com.sqx.modules.health.dto.UserDTO;
import com.sqx.modules.health.dto.UserPasswordDTO;
import com.sqx.modules.health.entity.*;
import com.sqx.modules.health.exception.ServiceException;
import com.sqx.modules.health.mapper.RoleMapper;
import com.sqx.modules.health.mapper.RoleMenuMapper;
import com.sqx.modules.health.mapper.UserMapper;
import com.sqx.modules.health.service.IAppCustomsService;
import com.sqx.modules.health.service.IMenuService;
import com.sqx.modules.health.service.IUserService;
import com.sqx.modules.health.utils.ObjectUtils;
//import com.sqx.modules.health.utils.TokenUtils;
import com.sqx.modules.sys.entity.SysUserEntity;
import com.sqx.modules.sys.service.SysUserService;
import io.netty.util.internal.StringUtil;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户信息	 服务实现类
 * </p>
 *
 * @author gxy
 * @since 2022-04-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, SysUserEntity> implements IUserService {

    private static final Log LOG = Log.get();

    private static final String USER_INFO_REDIS_KEY = "USER_INFO_";
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private IAppCustomsService customsService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    public Result appLoginByHealth(SysUserEntity userDto) {
        //用户信息
        SysUserEntity user = sysUserService.queryByUserName(userDto.getPhone());
        //账号不存在、密码错误
        if (user == null || !user.getPassword().equals(new Sha256Hash(userDto.getPassword(), user.getSalt()).toHex())) {
            return Result.error("账号或密码不正确");
        }
        //账号锁定
        if (user.getStatus() == 0) {
            return Result.error("账号已被锁定,请联系管理员");
        }
        if (user.getUserType() == 2) {
            return Result.error("请前往商家端进行登录！");
        }
        if (user.getType() != 0) {
            return Result.error("请使用患者账号登录！");
        }
        return getLoginResult(user);
    }

    @Override
    public UserDTO login(UserDTO userDTO) {
        SysUserEntity one = getUserInfo(userDTO);
        if (one != null) {
            BeanUtil.copyProperties(one, userDTO, true);
            // 设置token
            //String token = TokenUtils.genToken(one.getId().toString(), one.getPassword());
            //userDTO.setToken(token);

            String role = one.getRole(); // ROLE_ADMIN

            userDTO.setRole(role);

            // 设置用户的菜单列表
            List<Menu> roleMenus = getRoleMenus(role);
            userDTO.setMenus(roleMenus);
            return userDTO;
        } else {
            throw new ServiceException(Constants.CODE_600, "用户名或密码错误");
        }
    }

    @Override
    public SysUserEntity appPatientLogin(SysUserEntity user) {
        SysUserEntity one = getPatientUserInfo(user);
        if (one != null) {
            BeanUtil.copyProperties(one, user, true);
            // 设置token
            //String token = TokenUtils.genToken(one.getId().toString(), one.getPassword());
            //user.setToken(token);

            return user;
        } else {
            throw new ServiceException(Constants.CODE_600, "用户名或密码错误");
        }
    }

    @Override
    public SysUserEntity appPatientRegister(SysUserEntity user) {

        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", user.getPhone());
        SysUserEntity oneUser = getOne(queryWrapper); // 从数据库查询用户信息

        if (oneUser == null) {
            oneUser = new SysUserEntity();
            BeanUtil.copyProperties(user, oneUser, true);
            // 默认一个普通用户的角色
            oneUser.setRole(RoleEnum.ROLE_USER.toString());
            oneUser.setGender(ObjectUtils.judgeGender(oneUser.getCardid()));
            oneUser.setAge(ObjectUtils.countAge(oneUser.getCardid()));
            save(oneUser);  // 把 copy完之后的用户对象存储到数据库

            SysUserEntity oneaUser = getOne(queryWrapper); // 从数据库查询用户信息

            AppCustoms customs = new AppCustoms();
            customs.setUid(oneaUser.getUserId());
            customs.setType(1);
            customs.setBreakfaststartdate("05:00-08:00");
            customs.setBreakfastenddate("08:00-10:00");
            customs.setLunchstartdate("10:00-12:00");
            customs.setLunchenddate("12:00-15:00");
            customs.setDinnerstartdate("15:00-18:00");
            customs.setDinnerenddate("18:00-20:00");
            customs.setSleepstart("22:00-24:00");
            customs.setSleepend("00:00-05:00");
            customs.setCreatedate(LocalDateTime.now());
            customsService.save(customs);

        } else {
            throw new ServiceException(Constants.CODE_600, "用户已存在");
        }
        return oneUser;
    }

    @Override
    public SysUserEntity register(UserDTO userDTO) {
        SysUserEntity one = getUserInfo(userDTO);
        if (one == null) {
            one = new SysUserEntity();
            BeanUtil.copyProperties(userDTO, one, true);
            // 默认一个普通用户的角色
            one.setRole(RoleEnum.ROLE_USER.toString());
            save(one);  // 把 copy完之后的用户对象存储到数据库
        } else {
            throw new ServiceException(Constants.CODE_600, "用户已存在");
        }
        return one;
    }

    @Override
    public boolean updatePassword(UserPasswordDTO userPasswordDTO) {
        boolean update = userMapper.updatePassword(userPasswordDTO);
        if (!update) {
            throw new ServiceException(Constants.CODE_600, "密码错误");
        }
        return true;
    }

    @Override
    public SysUserEntity findRole(Long loginId, RoleEnum roleUser) {
        return userMapper.findRole(loginId, roleUser);
    }

    @Override
    public SysUserEntity findByOpenid(String openid) {
        return userMapper.findByOpenid(openid);
    }

    @Override
    public SysUserEntity findByPhone(String phone) {

//        User doctorUser = userMapper.findByPhone(phone);
//        if (doctorUser == null) {
//            throw new ServiceException(Constants.CODE_600, "该医生不存在");
//        }
//        return doctorUser;

        return userMapper.findByPhone(phone);
    }

    @Override
    public SysUserEntity findByUid(String uid) {
        return userMapper.findByUid(uid);
    }

    @Override
    public SysUserEntity findByToken(String token) {
        return userMapper.findByToken(token);
    }

    @Override
    public SysUserEntity searchUser(String openid) {
        return userMapper.searchUser(openid);
    }

    @Override
    public void updateToken(SysUserEntity user) {
        userMapper.updateToken(user);
    }

    @Override
    public List<UserDevice> getUserDevice(Long id) {
        return userMapper.getUserDevice(id);
    }

    @Override
    public void UserUnBinding(Long uid, Long deviceid) {
        userMapper.UserUnBinding(uid, deviceid);
    }

    @Override
    public List<Agent> findAllOperation(String uid, Long id) {
        return userMapper.findAllOperation(uid, id);
    }

    @Override
    public List<String> getResult(Long hid) {
        return userMapper.getResult(hid);
    }

    private SysUserEntity getUserInfo(UserDTO userDTO) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", userDTO.getPhone());
        queryWrapper.eq("password", userDTO.getPassword());
        queryWrapper.ne("type", 0);
        SysUserEntity one;
        try {
            one = getOne(queryWrapper); // 从数据库查询用户信息
        } catch (Exception e) {
            LOG.error(e);
            throw new ServiceException(Constants.CODE_500, "系统错误");
        }
        return one;
    }

    private SysUserEntity getPatientUserInfo(SysUserEntity user) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", user.getPhone());
        queryWrapper.eq("password", user.getPassword());
//        queryWrapper.eq("type", 0);
        SysUserEntity one;
        try {
            one = getOne(queryWrapper); // 从数据库查询用户信息
        } catch (Exception e) {
            LOG.error(e);
            throw new ServiceException(Constants.CODE_500, "系统错误");
        }
        return one;
    }


    /**
     * 获取当前角色的菜单列表
     *
     * @param roleFlag
     * @return
     */
    private List<Menu> getRoleMenus(String roleFlag) {
        Integer roleId = roleMapper.selectByFlag(roleFlag);
        // 当前角色的所有菜单id集合
        List<Integer> menuIds = roleMenuMapper.selectByRoleId(roleId);

        // 查出系统所有的菜单(树形)
        List<Menu> menus = menuService.findMenus("");
        // new一个最后筛选完成之后的list
        List<Menu> roleMenus = new ArrayList<>();
        // 筛选当前用户角色的菜单
        for (Menu menu : menus) {
            if (menuIds.contains(menu.getId())) {
                roleMenus.add(menu);
            }
            List<Menu> children = menu.getChildren();
            // removeIf()  移除 children 里面不在 menuIds集合中的 元素
            children.removeIf(child -> !menuIds.contains(child.getId()));
        }
        return roleMenus;
    }

    @Override
    public boolean save(SysUserEntity entity) {
        int insert = userMapper.insert(entity);
        redisUtils.set(USER_INFO_REDIS_KEY + entity.getUserId(), JSONObject.toJSONString(entity));
        return insert == 1;
    }

    @Override
    public boolean update(SysUserEntity entity) {
        return userMapper.insert(entity) == 1;
    }

    @Override
    public SysUserEntity getRedisByUid(String uid) {
        String userInfoJsonString = redisUtils.get(USER_INFO_REDIS_KEY + uid);
        SysUserEntity user;
        if (StringUtil.isNullOrEmpty(userInfoJsonString)) {
            user = this.getById(uid);
            redisUtils.set(USER_INFO_REDIS_KEY + uid, JSONObject.toJSONString(user));
        } else {
            user = JSONObject.parseObject(userInfoJsonString, SysUserEntity.class);
        }
        return user;
    }

    @Override
    public SysUserEntity getRedisByUid(Long uid) {
        String userInfoJsonString = redisUtils.get(USER_INFO_REDIS_KEY + uid);
        SysUserEntity user;
        if (StringUtil.isNullOrEmpty(userInfoJsonString)) {
            user = this.getById(uid);
            redisUtils.set(USER_INFO_REDIS_KEY + uid, JSONObject.toJSONString(user));
        } else {
            user = JSONObject.parseObject(userInfoJsonString, SysUserEntity.class);
        }
        return user;
    }

    @Override
    public boolean updateById(SysUserEntity entity) {
        redisUtils.set(USER_INFO_REDIS_KEY + entity.getUserId(), JSONObject.toJSONString(entity));
        int i = baseMapper.updateById(entity);
        return i == 1;
    }

    @Override
    public boolean saveOrUpdate(SysUserEntity entity) {
        if (entity.getUserId() == null) {
            return this.save(entity);
        } else {
            return this.updateById(entity);
        }
    }

    public Result getLoginResult(SysUserEntity user) {
        //生成token
        String token = jwtUtils.generateToken(user.getUserId());
        user.setToken(token);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());
        map.put("user", user);
        return Result.success(map);
    }


}
